/**
 *
 */
package com.nightwalker.xsite.dao;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.sql.Blob;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Time;
import java.sql.Timestamp;
import java.text.ParseException;
import java.util.Calendar;
import java.util.List;

import com.nightwalker.xsite.bean.ArquivoBean;
import com.nightwalker.xsite.bean.ObraBean;
import com.nightwalker.xsite.bean.ObraBeanPesquisa;
import com.nightwalker.xsite.infra.ErroDeSistemaException;
import com.nightwalker.xsite.infra.ErroGraveException;

/**
 * ObraDAO <br>
 * <br>
 * <b>Description:</b> Classe que gerencia os acessos a dados relacionados a
 * obras. <br>
 * <br>
 * Created in Jan 27, 2008 6:32:30 PM <br>
 * <b>version:</b> 1.0 <br>
 * <b>Modifications:</b>
 */
public class ObraDAO extends Dao {

	public void inserirObra(ObraBean obra) throws ErroDeSistemaException {
		PreparedStatement preparedStatement = null;

		StringBuilder query = new StringBuilder("INSERT INTO obras ");
		query.append("(titulo, ");
		query.append(" comentario, ");
		query.append(" nota, ");
		query.append(" data, ");
		query.append(" data_inclusao, ");
		query.append(" duracao, ");
		query.append(" preco, ");
		query.append(" tipo, ");
		query.append(" autor, ");
		query.append(" distribuidora, ");
		query.append(" arquivo, ");
		query.append(" nome )");
		query.append(" VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");

		try {
			log.debug("Inserindo uma obra: " + query.toString());
			preparedStatement = conexao.prepareStatement(query.toString());

			preparedStatement.setString(1, obra.getTitulo());
			preparedStatement.setString(2, obra.getComentario());
			preparedStatement.setFloat(3, Float.parseFloat(obra.getNota()));

			Date data_inclusao = new Date(Calendar.getInstance().getTimeInMillis());
			Date data = new Date(formatarData(obra.getData(), "dd/MM/yyyy").getTime());

			preparedStatement.setDate(4, data);

			preparedStatement.setTimestamp(5, new Timestamp(data_inclusao.getTime()));

			Time duracao = null;
			if ((obra.getDuracao() == null) || (obra.getDuracao().equals(""))){
				duracao = new Time(formatarData("00:00", "mm:ss").getTime());
			} else {
				duracao = new Time(formatarData(obra.getDuracao(), "mm:ss").getTime());
			}

			preparedStatement.setTime(6, duracao);

			preparedStatement.setFloat(7, Float.parseFloat(obra.getPreco()));

			// TODO Implementar tipo, artista e distribuidora.
			preparedStatement.setInt(8, Integer.parseInt(obra.getTipoId()));
			preparedStatement.setInt(9, Integer.parseInt(obra.getAutorId()));
			preparedStatement.setInt(10, 1);

			ByteArrayInputStream arquivo = new ByteArrayInputStream(obra.getArquivo().getBytes());

			preparedStatement.setBinaryStream(11, arquivo, obra.getArquivo().getBytes().length);
			preparedStatement.setString(12, obra.getArquivo().getName());

			log.debug("Executando query");
			preparedStatement.executeUpdate();

		} catch (SQLException e) {
			log.error("Erro ao incluir obra: ", e);
			throw new ErroDeSistemaException(e);
		} catch (ParseException e) {
			log.error("Erro ao fazer parse de uma data: ", e);
			throw new ErroGraveException(e);
		} catch (IOException e) {
			log.error("Erro de io: ", e);
			throw new ErroDeSistemaException(e);
		} finally {
			if (preparedStatement != null) {
				try {
					preparedStatement.close();
				} catch (SQLException e) {
					log.error("Erro fechando prepared Statment: ", e);
					throw new ErroGraveException(e);
				}
			}
		}
	}

	public ObraBeanPesquisa pesquisarObra(ObraBeanPesquisa obra) {

		PreparedStatement preparedStatement = null;
		ResultSet resultSet = null;
		List<ObraBeanPesquisa> obras = obra.getObras();

		StringBuilder query = new StringBuilder(
				"select id, titulo, duracao, comentario, nota, data from obras ");
		query.append("where 1=1");
		int contador = 0;

		if ((obra.getTitulo() != null) && (!obra.getTitulo().equals(""))) {
			query.append(" and titulo like ?");
			contador++;
		}

		if ((obra.getComentario() != null) && (!obra.getComentario().equals(""))) {
			query.append(" and comentario like ?");
			contador++;
		}

		/*
		 * Podem existir 3 casos para as notas:
		 * Vir apenas notaInicio
		 * Vir apenas notaFinal
		 * Virem as duas notas
		 *
		 *  TODO Logica muito complicada
		 */

		if ((obra.getNotaInicio() != null) && (!obra.getNotaInicio().equals(""))) {
			query.append(" and nota >= ?");
			contador++;
		}

		if ((obra.getNotaFinal() != null) && (!obra.getNotaFinal().equals(""))) {
			query.append(" and nota <= ?");
			contador++;
		}

		if ((obra.getDataInicio() != null) && (!obra.getDataInicio().equals(""))) {
			query.append(" and data >= ?");
			contador++;
		}

		if ((obra.getDataFinal() != null) && (!obra.getDataFinal().equals(""))) {
			query.append(" and data <= ?");
			contador++;
		}

		try {
			log.debug("Pesquisando obra(Preparando statment): " + query.toString());
			preparedStatement = conexao.prepareStatement(query.toString());

			if ((obra.getDataFinal() != null) && (!obra.getDataFinal().equals(""))) {
				preparedStatement.setDate(contador, new Date(formatarData(obra.getDataFinal(),
						"dd/MM/yyyy").getTime()));
				contador--;
			}

			if ((obra.getDataInicio() != null) && (!obra.getDataInicio().equals(""))) {
				preparedStatement.setDate(contador, new Date(formatarData(obra.getDataInicio(),
						"dd/MM/yyyy").getTime()));
				contador--;
			}

			if ((obra.getNotaFinal() != null) && (!obra.getNotaFinal().equals(""))) {
				preparedStatement.setFloat(contador, Float.parseFloat(obra.getNotaFinal()));
				contador--;
			}

			if ((obra.getNotaInicio() != null) && (!obra.getNotaInicio().equals(""))) {
				preparedStatement.setFloat(contador, Float.parseFloat(obra.getNotaInicio()));
				contador--;
			}

			if ((obra.getComentario() != null) && (!obra.getComentario().equals(""))) {
				preparedStatement.setString(contador, "%" + obra.getComentario() + "%");

				contador--;
			}

			if ((obra.getTitulo() != null) && (!obra.getTitulo().equals(""))) {
				preparedStatement.setString(contador, "%" + obra.getTitulo() + "%");
			}

			log.debug("Pesquisando obra(executando query)");
			resultSet = preparedStatement.executeQuery();

			ObraBeanPesquisa obraOut;
			while (resultSet.next()) {
				obraOut = new ObraBeanPesquisa();
				obraOut.setTitulo(resultSet.getString("titulo"));
				obraOut.setDuracao(String.valueOf(resultSet.getTime("duracao")));
				obraOut.setComentario(resultSet.getString("comentario"));
				obraOut.setId(String.valueOf(resultSet.getInt("id")));
				obraOut.setNota(resultSet.getString("nota"));
				obraOut.setData(formatarData(resultSet.getDate("data"), "dd/MM/yyyy"));

				obras.add(obraOut);
			}

			log.debug("Encontrados " + obras.size() + " obras na pesquisa");

			return obra;
		} catch (SQLException e) {
			log.error("Erro ao pesquisar obra: ", e);
			throw new ErroGraveException(e);
		} catch (ParseException e) {
			log.error("Erro ao formatar data: ", e);
			throw new ErroGraveException(e);
		} finally {
			try {
				if (resultSet != null) {
					resultSet.close();
				}
				if (preparedStatement != null) {
					preparedStatement.close();
				}

			} catch (SQLException e) {
				log.error("Erro ao fechar result set/prepared statment: ", e);
				throw new ErroGraveException(e);
			}
		}

	}

	public ArquivoBean retrieveArquivo(int chave) throws ErroDeSistemaException {

		ArquivoBean arquivo = new ArquivoBean();
		PreparedStatement preparedStatement = null;
		ResultSet resultSet = null;
		byte[] arquivoBt = null;
		String nome = null;

		StringBuilder query = new StringBuilder("SELECT ");
		query.append("arquivo, nome ");
		query.append("FROM obras f ");
		query.append("WHERE f.id = ?");

		try {
			log.debug("Recuperando arquivo (Preparando statment): " + query.toString());
			log.debug("Recuperando arquivo de id: " + chave);
			preparedStatement = conexao.prepareStatement(query.toString());
			preparedStatement.setInt(1, chave);

			log.debug("Recuperando arquivo (Executando query)");
			resultSet = preparedStatement.executeQuery();

			Blob blob = null;
			if (resultSet.next()) {
				blob = resultSet.getBlob("arquivo");
				nome = resultSet.getString("nome");
			}

			arquivoBt = blob.getBytes(1, (int) blob.length());

			log.debug("Arquivo de " + blob.length()/(1024*1024) + " megabytes recuperado");

		} catch (SQLException e) {
			log.error("Erro de SQL ao recuperar arquivo: ", e);
			throw new ErroDeSistemaException(e);
		} finally {
			try {
				if (resultSet != null) {
					resultSet.close();
				}

				if (preparedStatement != null) {
					preparedStatement.close();
				}
			} catch (SQLException e) {
				log.error("Erro ao fechar result set/prepared statment: ", e);
				throw new ErroGraveException(e);
			}

		}

		arquivo.setArquivo(arquivoBt);
		arquivo.setNome(nome);
		arquivo.setTipo(getExtencion(nome));

		return arquivo;
	}

	private String getExtencion(String nome){
		String nomes[] = nome.split("\\.");

		return nomes[nomes.length - 1];

	}


}
